package cn.yj.common.monitor;

import cn.yj.common.emums.PayType;
import cn.yj.common.entity.PayOrder;
import cn.yj.common.entity.PayRefundOrder;
import cn.yj.common.entity.RefundQueryParams;
import cn.yj.common.interfaces.AbstractPay;
import cn.yj.wx.pay.emums.PayOrderWechatStatus;
import cn.yj.wx.pay.emums.RefundWechatStatus;

import java.util.concurrent.TimeUnit;

/**
 * @author 永健
 * @since 2022-02-21 10:06
 */
public class WechatOrderMonitor extends AbstractPayOrderMonitor {


    /**
     * 注意：要生成退款订单后才可以
     *
     * @param params 退款参数
     */
    @Override
    public void refundMonitor(RefundQueryParams params, AbstractPay abstractPay) {
        PayRefundOrder payRefundOrder = abstractPay.queryRefundOrder(params);
        if (payRefundOrder.isSuccess()) {
            notifyRefundHandler.syncNotify(PayType.WECHAT, true, params.getOutTradeNo());
        } else {
            this.loopOrderPayRefundStatus(params, 10, 10, abstractPay);
        }
    }

    /**
     * 注：需要在支付平台生成订单后调用
     *
     * @param outTradeNo 商户订单号
     */
    @Override
    public void payMonitor(long expireTime, String outTradeNo, AbstractPay abstractPay) {
        PayOrder payOrder = abstractPay.queryOrder(outTradeNo);
        this.loopOrderPayStatus(expireTime, payOrder, 10, abstractPay);
    }


    /**
     * 递归 count 次数去查询退款结果
     *
     * @param params 订单
     * @param delay  延迟多长时间执行单位秒
     * @param count  最多查询多少次
     */
    private void loopOrderPayRefundStatus(RefundQueryParams params, long delay, int count, AbstractPay abstractPay) {
        if (count <= 0) {
            return;
        }
        --count;
        int finalCount = count;
        scheduledExecutorService.schedule(() -> {
            PayRefundOrder payOrder;
            try {
                payOrder = abstractPay.queryRefundOrder(params);
                if (payOrder.isSuccess()) {
                    notifyRefundHandler.syncNotify(PayType.WECHAT, true, params.getOutTradeNo());
                    return;
                }
                if (!payOrder.isSuccess()) {
                    if (RefundWechatStatus.PROCESSING.name().equals(payOrder.getStatus())) {
                        if (finalCount <= 0) {
                            // 在来十次
                            this.loopOrderPayRefundStatus(params, delay, 10, abstractPay);
                            return;
                        }
                        this.loopOrderPayRefundStatus(params, delay, finalCount, abstractPay);
                    }
                } else if (payOrder.getStatus().equals(RefundWechatStatus.ABNORMAL.name())) {
                    notifyRefundHandler.syncNotify(PayType.WECHAT, false, params.getOutTradeNo());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, delay, TimeUnit.SECONDS);
    }


    /**
     * 递归 count 次数去查询支付结果
     *
     * @param order      订单
     * @param delay      延迟多长时间执行单位秒
     * @param expireTime 支付超时时间
     */
    private void loopOrderPayStatus(long expireTime, PayOrder order, long delay, AbstractPay abstractPay) {
        if (System.currentTimeMillis() > expireTime) {
            return;
        }
        scheduledExecutorService.schedule(() -> {
            PayOrder payOrder;
            try {
                payOrder = abstractPay.queryOrder(order.getOutTradeNo());
                if (payOrder.isSuccess()) {
                    notifyHandler.syncNotify(PayType.WECHAT, order.getOutTradeNo());
                    return;
                }
                if (!payOrder.isSuccess()) {
                    if (PayOrderWechatStatus.USERPAYING.name().equals(payOrder.getTradeStatus()) || PayOrderWechatStatus.NOTPAY.name().equals(payOrder.getTradeStatus())) {
                        this.loopOrderPayStatus(expireTime, payOrder, delay, abstractPay);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, delay, TimeUnit.SECONDS);
    }
}
